package com.murong.ai.coder.domain;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.murong.ai.coder.entity.GlobalProperties;
import com.murong.ai.coder.entity.TableEntity;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.nio.file.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class GenerateCodeService {
    private static final Logger log = LoggerFactory.getLogger(GenerateCodeService.class);
    @Autowired
    GlobalProperties globalProperties;
    @Autowired
    Configuration cfg;

    @SneakyThrows
    public void generTableCode(TableEntity entity) {
        if (entity == null) {
            log.error("TableEntity 为空，无法生成代码");
            return;
        }
        Map<String, Object> dataModel = new HashMap<>();
        dataModel.put("table", entity);

        String basePath = globalProperties.getBaseUrl().getPath();
        if (basePath == null || basePath.isEmpty()) {
            log.error("basePath 为空");
            return;
        }
        if (!basePath.endsWith("/")) {
            basePath = basePath + "/";
        }

        GlobalProperties.ClassPath classPath = globalProperties.getModules().getModuleWeb().getClassPath();
        GlobalProperties.Resources resources = globalProperties.getModules().getModuleWeb().getResources();
        String classMiddlePath = classPath.getPath();
        if (classMiddlePath == null || classMiddlePath.isEmpty()) {
            log.error("classMiddlePath 为空");
            return;
        }
        if (!classMiddlePath.endsWith("/")) {
            classMiddlePath = classMiddlePath + "/";
        }

        String resourcesMiddlePath = resources.getPath();
        if (resourcesMiddlePath == null || resourcesMiddlePath.isEmpty()) {
            log.error("resourcesMiddlePath 为空");
            return;
        }
        if (!resourcesMiddlePath.endsWith("/")) {
            resourcesMiddlePath = resourcesMiddlePath + "/";
        }

        entity.getProperties().setEntityPath(classPath.getTableEntity().getPath());
        entity.getProperties().setMapperPath(classPath.getTableMapper().getPath());
        entity.getProperties().setXmlPath(resources.getTableMapperXml().getPath());

        TableEntity.Properties prop = entity.getProperties();
        String entityPath = prop.getEntityPath() == null ? "" : prop.getEntityPath().replaceAll("\\.", "/");
        String mapperPath = prop.getMapperPath() == null ? "" : prop.getMapperPath().replaceAll("\\.", "/");
        String xmlPath = prop.getXmlPath() == null ? "" : prop.getXmlPath();
        String tableName = entity.getTableNameCamel();


        generateFile(cfg, "table-entity.ftl", dataModel, basePath+classMiddlePath+entityPath + "/" + tableName + "PO.java");
        generateFile(cfg, "table-mapper.ftl", dataModel, basePath+classMiddlePath+mapperPath + "/" + tableName + "Mapper.java");
        generateFile(cfg, "table-mapper-xml.ftl", dataModel, basePath+resourcesMiddlePath+xmlPath + "/"+ tableName + "Mapper.xml");

        File expMappFile = new File(basePath+classMiddlePath+mapperPath + "/" + tableName + "ExtMapper.java");
        if(!expMappFile.exists()){
            generateFile(cfg, "table-exp-mapper.ftl", dataModel, basePath+classMiddlePath+mapperPath + "/" + tableName + "ExtMapper.java");
        }
        File expXmlFile = new File(basePath+resourcesMiddlePath+xmlPath + "/"+ tableName + "ExtMapper.xml");
        if(!expXmlFile.exists()){
            generateFile(cfg, "table-exp-mapper-xml.ftl", dataModel, basePath+resourcesMiddlePath+xmlPath + "/"+ tableName + "ExtMapper.xml");
        }
    }

    private void generateFile(Configuration cfg, String templateName, Map<String, Object> dataModel, String outputPath) throws IOException, TemplateException {
        Template template = cfg.getTemplate(templateName);
        File outFile = new File(outputPath);
        if (!outFile.getParentFile().exists()) {
            outFile.getParentFile().mkdirs();
        }
        try (Writer writer = new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8)) {
            template.process(dataModel, writer);
        }
    }
}
